/**
* Copyright (c) By zengqh.
*
* This program is just for fun or demo, in the hope that it  
* will be useful, you can redistribute it and/or modify freely.
*
* Time: 2012/07/16
* File: RenderWin32.cpp
* Blog: http://www.cnblogs.com/zengqh/
**/

#include "../../Config/Config.h"

#ifdef RF_PLATFORM_WINDOWS

#include <windows.h>
#include "RenderWin32.h"

RenderWin32* g_render_win32 = NULL;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{
	case WM_SIZE:
		g_render_win32->onWindowSizeChange(LOWORD(lParam), HIWORD(lParam));
		break;
	}

	return ::DefWindowProc(hWnd, message, wParam, lParam);
}


RenderWin32::RenderWin32()
{
	g_render_win32 = this;
}

RenderWin32::~RenderWin32()
{

}

bool RenderWin32::createWindow(const CreateWindowParams& param)
{
	_window_params = param;
	return createWindowImpl();
}

bool RenderWin32::createWindowImpl()
{
	_app_instance = GetModuleHandle(0);

	const char* class_name = "DeviceWin32";

	WNDCLASSEX wcex;
	wcex.cbSize			= sizeof(WNDCLASSEX);
	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= _app_instance;
	wcex.hIcon			= NULL;
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= 0;
	wcex.lpszClassName	= class_name;
	wcex.hIconSm		= 0;

	RegisterClassEx(&wcex);

	RECT clientSize;
	clientSize.top = 0;
	clientSize.left = 0;
	clientSize.right = _window_params._window_dimension._width;
	clientSize.bottom = _window_params._window_dimension._height;

	DWORD style = WS_OVERLAPPEDWINDOW;

	AdjustWindowRect(&clientSize, style, FALSE);

	const s32 realWidth = clientSize.right - clientSize.left;
	const s32 realHeight = clientSize.bottom - clientSize.top;

	s32 windowLeft = (GetSystemMetrics(SM_CXSCREEN) - realWidth) / 2;
	s32 windowTop = (GetSystemMetrics(SM_CYSCREEN) - realHeight) / 2;

	if ( windowLeft < 0 )
		windowLeft = 0;
	if ( windowTop < 0 )
		windowTop = 0;	// make sure window menus are in screen on creation

	_window_id = (u32)CreateWindow( class_name, ("RF"), style, windowLeft, windowTop,
		realWidth, realHeight, NULL, NULL, _app_instance, NULL);

	_window_hdc = ::GetDC((HWND)_window_id);

	ShowWindow((HWND)_window_id, SW_SHOW);
	UpdateWindow((HWND)_window_id);

	MoveWindow((HWND)_window_id, windowLeft, windowTop, realWidth, realHeight, TRUE);

	return true;
}

bool RenderWin32::isWindowActive() const
{
	return ::GetActiveWindow() == (HWND)_window_id;
}

HINSTANCE RenderWin32::getAppInstance() const
{
	return _app_instance;
}

u32 RenderWin32::getWindowID() const
{
	return _window_id;
}

HDC RenderWin32::getWindowDC() const
{
	return _window_hdc;
}

void RenderWin32::onWindowSizeChange(s32 w, s32 h)
{
	_dimension._width = w;
	_dimension._height = h;

	Recti viewport;
	viewport._left_top.x = 0;
	viewport._left_top.y = 0;
	viewport._right_bottom.x = w;
	viewport._right_bottom.y = h;

	RenderTargetListeneList::iterator iter = _render_target_listener_list.begin();
	for(; iter != _render_target_listener_list.end(); ++iter)
	{
		(*iter)->onViewportUpdate(viewport);
	}
}

#endif